# -*- coding: utf-8 -*-
import datetime
import json

from django.http import JsonResponse
from django.shortcuts import render
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.views.decorators.csrf import csrf_exempt

from utils.encrypt import uid
from utils.pagination import Pagination
from web import models
from web.forms.issues import IssuesModelForm, IssuesReplyModelForm, InviteModelForm


class CheckFilter(object):
    def __init__(self, name, data_list, request):
        self.name = name
        self.data_list = data_list
        self.request = request

    def __iter__(self):
        for item in self.data_list:
            k = str(item[0])
            v = item[1]
            ck = ''
            # 处理被勾上的
            value_list = self.request.GET.getlist(self.name)
            if k in value_list:
                ck = 'checked'
                value_list.remove(k)
            else:
                value_list.append(k)

            # 生成url
            query_dict = self.request.GET.copy()
            query_dict._mutable = True  # 让query_list可以修改
            query_dict.setlist(self.name, value_list)  # 结果：status=11&status=22...

            # 移除分页
            if 'page' in query_dict:
                query_dict.pop('page')

            # 去除？
            param_url = query_dict.urlencode()
            if param_url:
                # {'status': [1, 2, 3]} => query_list.urlencode() => status=1&status=2....
                url = '{}?{}'.format(self.request.path_info, query_dict.urlencode())
            else:
                url = self.request.path_info

            html = """
                <a class="cell" href="{url}"><input type="checkbox" {ck} id="{id}" /><label for="{id}">{text}</label></a>
                """.format(url=url, ck=ck, id='', text=v)

            yield mark_safe(html)


class SelectFilter(object):
    def __init__(self, name, data_list, request):
        self.name = name
        self.data_list = data_list
        self.request = request

    def __iter__(self):
        yield mark_safe('<select class="select2" multiple="multiple" style="width: 100%;">')
        for item in self.data_list:

            k = str(item[0])
            v = item[1]

            value_list = self.request.GET.getlist(self.name)
            selected = ''
            if k in value_list:
                selected = 'selected'
                value_list.remove(k)
            else:
                value_list.append(k)

            query_dict = self.request.GET.copy()
            query_dict._mutable = True  # 让query_list可以修改
            query_dict.setlist(self.name, value_list)  # 结果：status=11&status=22...

            # 移除分页
            if 'page' in query_dict:
                query_dict.pop('page')

            # 去除？
            param_url = query_dict.urlencode()
            if param_url:
                # {'status': [1, 2, 3]} => query_list.urlencode() => status=1&status=2....
                url = '{}?{}'.format(self.request.path_info, query_dict.urlencode())
            else:
                url = self.request.path_info

            html = '<option value="{url}" {selected} >{v}</option>'.format(url=url, selected=selected, v=v)
            yield mark_safe(html)
        yield mark_safe('</select>')


def issues(request, project_id):
    """问题"""
    if request.method == 'GET':

        # 根据筛选条件，获取对应的数据
        allow_filter_name = ['issues_type', 'status', 'priority', 'assign', 'attention']
        condition = {}

        for name in allow_filter_name:
            value_list = request.GET.getlist(name)
            if not value_list:
                continue
            condition['{}__in'.format(name)] = value_list

        # 分页
        queryset = models.Issues.objects.filter(project_id=project_id).filter(**condition)
        paginator = Pagination(
            current_page=request.GET.get('page'),
            all_count=queryset.count(),
            base_url=request.path_info,
            query_params=request.GET,
            per_page=25
        )
        issues_obj_list = queryset[paginator.start: paginator.end]

        form = IssuesModelForm(request)
        project_issues_type = models.IssuesType.objects.filter(project_id=project_id).values_list('id', 'title')
        project_total_user = [(request.tracer.project.creator_id, request.tracer.project.creator.name)]
        participant = models.Participant.objects.filter(project_id=project_id).values_list('user_id', 'user__name')
        project_total_user.extend(participant)

        # 邀请的modelform
        invite_form = InviteModelForm()
        context = {
            'form': form,
            'invite_form': invite_form,
            'issues_obj_list': issues_obj_list,
            'page_html': paginator.page_html(),
            'filter_list': [
                {'title': '问题类型', 'filter': CheckFilter('issues_type', project_issues_type, request)},
                {'title': '状态', 'filter': CheckFilter('status', models.Issues.status_choices, request)},
                {'title': '优先级', 'filter': CheckFilter('priority', models.Issues.priority_choices, request)},
                {'title': '指派', 'filter': SelectFilter('assign', project_total_user, request)},
                {'title': '关注', 'filter': SelectFilter('attention', project_total_user, request)},
            ]
        }
        return render(request, 'issues.html', context)

    form = IssuesModelForm(request, data=request.POST)
    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.creator = request.tracer.user
        form.save()

        return JsonResponse({'status': True})

    return JsonResponse({'status': False, 'error': form.errors})


def issues_detail(request, project_id, issues_id):
    """问题详情和编辑"""
    issues_obj = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    # instance=obj：这样就可以真详情页看到数据了
    form = IssuesModelForm(request, instance=issues_obj)
    return render(request, 'issues_detail.html', {'form': form, 'issues_obj': issues_obj})


@csrf_exempt
def issues_record(request, project_id, issues_id):
    """初始化操作记录/评论"""
    if request.method == 'GET':
        reply_list = models.IssuesReply.objects.filter(issues_id=issues_id, issues__project=request.tracer.project)
        # 构造数据
        data_list = [{
            'id': item.id,
            'reply_type_text': item.get_reply_type_display(),
            'content': item.content,
            'creator': item.creator.name,
            'datetime': item.create_datetime.strftime('%Y-%m-%d %H:%M'),
            'parent_id': item.reply_id
        } for item in reply_list]

        return JsonResponse({'status': True, 'data': data_list})

    form = IssuesReplyModelForm(data=request.POST)
    if form.is_valid():
        form.instance.issues_id = issues_id
        form.instance.reply_type = 2
        form.instance.creator = request.tracer.user
        instance = form.save()
        info = {
            'id': instance.id,
            'reply_type_text': instance.get_reply_type_display(),
            'content': instance.content,
            'creator': instance.creator.name,
            'datetime': instance.create_datetime.strftime('%Y-%m-%d %H:%M'),
            'parent_id': instance.reply_id
        }
        return JsonResponse({'status': True, 'data': info})
    return JsonResponse({'status': False, 'error': form.errors})


@csrf_exempt
def issues_change(request, project_id, issues_id):
    """问题更新"""

    data = json.loads(request.body.decode('utf-8'))
    name = data.get('name')
    value = data.get('value')
    issues_obj = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    field_obj = models.Issues._meta.get_field(name)

    def create_reply_record(content):
        instance = models.IssuesReply.objects.create(reply_type=1, issues=issues_obj, content=op_log,
                                                     creator=request.tracer.user)
        info = {
            'id': instance.id,
            'reply_type_text': instance.get_reply_type_display(),
            'content': instance.content,
            'creator': request.tracer.user.name,
            'datetime': instance.create_datetime.strftime('%Y-%m-%d %H:%M'),
            'parent_id': instance.reply_id
        }
        return info

    # 1. 更新数据
    # 1.1 文本输入框
    if name in ['subject', 'desc', 'start_date', 'end_date']:
        if not value:
            if not field_obj.null:
                return JsonResponse({'status': False, 'error': '本字段不能为空.'})
            setattr(issues_obj, name, None)
            issues_obj.save()
            op_log = '{}更新为空'.format(field_obj.verbose_name)
        else:
            setattr(issues_obj, name, value)
            issues_obj.save()
            op_log = '{}更新为{}'.format(field_obj.verbose_name, value)

        return JsonResponse({'status': True, 'data': create_reply_record(op_log)})

    # 1.2 外键输入
    if name in ['issues_type', 'module', 'parent', 'assign']:
        if not value:
            if not field_obj.null:
                return JsonResponse({'status': False, 'error': '本字段不能为空.'})
            setattr(issues_obj, name, None)
            issues_obj.save()
            op_log = '{}更新为空'.format(field_obj.verbose_name)
        else:
            # 对指派进行特殊处理
            if name == 'assign':
                # 是否为项目的创建者
                if value == str(request.tracer.project.creator_id):
                    instance = request.tracer.project.creator
                else:
                    # 是否为项目的参与者
                    project_user_obj = models.Participant.objects.filter(project_id=project_id, user_id=value).first()
                    if project_user_obj:
                        instance = project_user_obj.user
                    else:
                        instance = None
                if not instance:
                    return JsonResponse({'status': False, 'error': '选择的值不存在.'})

                setattr(issues_obj, name, instance)
                issues_obj.save()
                op_log = '{}更新为{}'.format(field_obj.verbose_name, str(instance))

            else:
                # 判断是否是本问题的外键
                instance = field_obj.remote_field.model.objects.filter(id=value, project_id=project_id).first()
                if not instance:
                    return JsonResponse({'status': False, 'error': '选择的值不存在.'})

                setattr(issues_obj, name, instance)
                issues_obj.save()
                op_log = '{}更新为{}'.format(field_obj.verbose_name, str(instance))

        return JsonResponse({'status': True, 'data': create_reply_record(op_log)})

    # 1.3 choices
    if name in ['priority', 'status', 'mode']:
        selected_text = None
        for k, v in field_obj.choices:
            if str(k) == value:
                selected_text = v
        if not selected_text:
            return JsonResponse({'status': False, 'error': '选择的值不存在.'})

        setattr(issues_obj, name, value)
        issues_obj.save()
        op_log = '{}更新为{}'.format(field_obj.verbose_name, selected_text)
        return JsonResponse({'status': True, 'data': create_reply_record(op_log)})

    # 1.4 多对多
    if name == 'attention':
        if not isinstance(value, list):
            return JsonResponse({'status': False, 'error': '数据格式错误.'})

        # 没有指定谁需要关注
        if not value:
            # 多对多关联关系的更新
            issues_obj.attention.set([])
            issues_obj.save()
            op_log = '{}更新为空'.format(field_obj.verbose_name)
        else:
            # 当前项目的所有成员
            user_dict = {str(request.tracer.project.creator_id): request.tracer.project.creator.name}
            user_list = models.Participant.objects.filter(project_id=project_id)
            for item in user_list:
                user_dict[str(item.user_id)] = item.user.name

            username_list = []
            for user_id in value:
                username = user_dict.get(str(user_id))
                if not username:
                    return JsonResponse({'status': False, 'error': '用户数据错误'})
                username_list.append(username)
            issues_obj.attention.set(value)
            issues_obj.save()
            op_log = '{}更新为{}'.format(field_obj.verbose_name, ','.join(username_list))
        return JsonResponse({'status': True, 'data': create_reply_record(op_log)})

    return JsonResponse({'status': False, 'error': '非法操作'})


def invite_url(request, project_id):
    """生成邀请码"""

    form = InviteModelForm(data=request.POST)
    if form.is_valid():
        """
        1. 创建随机邀请码
        2. 保存邀请码
        3. 谁可以邀请
        """
        if request.tracer.user != request.tracer.project.creator:
            print('1')
            form.add_error('period', '没有足够的权限')
            return JsonResponse({'status': False, 'error': form.errors})

        invite_code = uid(request.tracer.user.phone)
        form.instance.project = request.tracer.project
        form.instance.code = invite_code
        form.instance.creator = request.tracer.user
        form.save()

        # 邀请url
        url = '{scheme}://{host}{path}'.format(scheme=request.scheme,
                                               host=request.get_host(),
                                               path=reverse('web:invite_join', kwargs={'code': invite_code}))
        print('2')
        return JsonResponse({'status': True, 'data': url})
    print('3')
    return JsonResponse({'status': False, 'error': form.errors})


def invite_join(request, code):
    """处理邀请链接"""

    current_time = datetime.datetime.now()

    invite_obj = models.ProjectInvite.objects.filter(code=code).first()
    if not invite_obj:
        return render(request, 'invite_join.html', {'error': '邀请码不存在'})

    if invite_obj.project.creator == request.tracer.user:
        return render(request, 'invite_join.html', {'error': '创建者不需要参加邀请'})

    exists = models.Participant.objects.filter(project=invite_obj.project, user=request.tracer.user).exists()
    if exists:
        return render(request, 'invite_join.html', {'error': '已加入项目'})

    # 判断套餐是否已经过期，过期了就使用免费的
    max_transaction = models.Transaction.objects.filter(user=invite_obj.project.creator).order_by('-id').first()
    if max_transaction.price_policy.category == 1:
        max_member = max_transaction.price_policy.project_member
    else:
        if max_transaction.end_datetime < current_time:
            free_obj = models.PricePolicy.objects.filter(category=1).first()
            max_member = free_obj.project_member
        else:
            max_member = max_transaction.price_policy.project_member

    # 目前所有项目成员
    current_member = models.Participant.objects.filter(project=invite_obj.project).count()
    current_member = current_member + 1  # + 创建者
    if current_member >= max_member:
        return render(request, 'invite_join.html', {'error': '成员容量已满'})

    # 创建时间 + 有效时间 转成分钟
    lose_time = invite_obj.create_datetime + datetime.timedelta(minutes=invite_obj.period)
    if current_time > lose_time:
        return render(request, 'invite_join.html', {'error': '邀请码已过期'})

    if invite_obj.count:
        # 有数量限制
        if invite_obj.use_count >= invite_obj.count:
            return render(request, 'invite_join.html', {'error': '邀请码可邀请人数已使用完'})

        invite_obj.use_count += 1
        invite_obj.save()

    # 没有数量限制
    models.Participant.objects.create(user=request.tracer.user, project=invite_obj.project)

    # 成员+1
    invite_obj.project.join_count += 1
    invite_obj.save()

    return render(request, 'invite_join.html', {'project': invite_obj.project})
